#include "asm.h"
#include "regdef.h"
#include "cpu_cde.h"

#define lab3  1
#define lab6  1
#define lab7  1
#define lab8  1
#define lab9  1

#ifdef ENABLE_TRACE
#define TEST_NUM (lab3*20 + lab6*16 + lab7*10 + lab8*1 + lab9*9)
#else
#define TEST_NUM (lab3*20 + lab6*16 + lab7*10 + lab8*1 + lab9*13)
#endif

##s0, number
##s1, number adress 
##s2, exception use
##s3, score
##s4, exception pc
	.globl	_start
	.globl	start
	.globl	__main
_start:
start:
    li     t0, 0xffffffff
    addi.w t0, zero, -1
	b	locate

##avoid "j locate" not taken
    lu12i.w   t0, -0x80000
    addi.w    t1, t1, 1
    or        t2, t0, zero
    add.w     t3, t5, t6
    ld.w      t4, t0, 0

##avoid cpu run error
.org 0x0ec
    lu12i.w   t0, -0x80000
    addi.w    t1, t1, 1
    or        t2, t0, zero
    add.w     t3, t5, t6
    ld.w      t4, t0, 0
.org 0x100
test_finish:
    addi.w    t0, t0, 1
    LI        (t2, UART_ADDR)
    st.w      zero, t2, 0
1:
    syscall 0x11

##avoid cpu run error
    lu12i.w   t0, -0x80000
    addi.w    t1, t1, 1
    or        t2, t0, zero
    add.w     t3, t5, t6
    ld.w      t4, t0, 0
/*
 *  exception handle
 */
.org 0x8000   //0x1c008000
1:  
    li    t0, 0x800d0000
    ld.w  t1, t0, 0 
    li    t0, 0x1 
    beq   t1, t0, syscall_ex  #syscall  
    li    t0, 0x2 
    beq   t1, t0, brk_ex      #break 
    li    t0, 0x3 
    beq   t1, t0, ine_ex      #reserved inst 
    li    t0, 0x4 
    beq   t1, t0, int_ex      #interrupt 
    li    t0, 0x5 
    beq   t1, t0, adef_ex     #adef 
    li    t0, 0x6 
    beq   t1, t0, ale_ex      #ale 
#   li    t0, 0x7 
#   beq   t1, t0, ipe_ex      #ipe
	b     test_end

syscall_ex:
    add.w    s2, zero, zero
    csrrd    t0, csr_era 
    bne      s4, t0, ex_finish 
    csrrd    t0, csr_estat 
    li       t1, 0x7fff0000 
    and      t0, t0, t1 
    li       t1, 0x000b0000 
    bne      t1, t0, ex_finish 
    csrrd    t0, csr_crmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    li       t1, 0x0 
    bne      t1, t0, ex_finish
    csrrd    t0, csr_prmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    bne      t0, t5, ex_finish 
    lu12i.w  s2, 0x10 
    b        ex_finish  

brk_ex: 
    add.w    s2, zero, zero
    csrrd    t0, csr_era 
    bne      s4, t0, ex_finish 
    csrrd    t0, csr_estat 
    li       t1, 0x7fff0000 
    and      t0, t0, t1 
    li       t1, 0x000c0000 
    bne      t1, t0, ex_finish 
    csrrd    t0, csr_crmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    li       t1, 0x0 
    bne      t1, t0, ex_finish
    csrrd    t0, csr_prmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    bne      t0, t5, ex_finish 
    lu12i.w  s2, 0x20 
    b        ex_finish  

ine_ex:
    add.w    s2, zero, zero
    csrrd    t0, csr_era 
    bne      s4, t0, ex_finish 
    csrrd    t0, csr_estat 
    li       t1, 0x7fff0000 
    and      t0, t0, t1 
    li       t1, 0x000d0000 
    bne      t1, t0, ex_finish 
    csrrd    t0, csr_crmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    li       t1, 0x0 
    bne      t1, t0, ex_finish
    csrrd    t0, csr_prmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    bne      t0, t5, ex_finish 
    lu12i.w  s2, 0x30 
    b        ex_finish 

int_ex:
    add.w    s2, zero, zero
    csrrd    t0, csr_era 
    bne      s4, t0, ex_finish 
    csrrd    t0, csr_estat 
    li       t1, 0x7fff0000 
    and      t0, t0, t1 
    li       t1, 0x00000000 
    bne      t1, t0, ex_finish 
    csrrd    t0, csr_crmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    li       t1, 0x0 
    bne      t1, t0, ex_finish
    csrrd    t0, csr_prmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    bne      t0, t5, ex_finish 
    li       t1, 0x1 
    csrwr    t1, csr_ticlr 
    bne      t1, zero, ex_finish 
    li       t1, 0x0 
    li       t0, 0x3 
    csrxchg  t1, t0, csr_estat 
    csrrd    t1, csr_estat
    li       t0, 0x1fff 
    and      t0, t0, t1 
    bne      t0, zero, ex_finish 
    lu12i.w  s2, 0x40 
    b        ex_finish 

adef_ex:
    add.w    s2, zero, zero
    csrwr    s5, csr_era
    bne      s4, s5, ex_finish 
    csrrd    t0, csr_estat 
    li       t1, 0x7fff0000 
    and      t0, t0, t1 
    li       t1, 0x00080000 
    bne      t1, t0, ex_finish 
    csrrd    t0, csr_crmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    li       t1, 0x0 
    bne      t1, t0, ex_finish
    csrrd    t0, csr_prmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    bne      t0, t5, ex_finish 
    lu12i.w  s2, 0x50 
    b        ex_finish  

ale_ex:
    add.w    s2, zero, zero
    csrrd    t0, csr_era 
    bne      s4, t0, ex_finish 
    csrrd    t0, csr_estat 
    li       t1, 0x7fff0000 
    and      t0, t0, t1 
    li       t1, 0x00090000 
    bne      t1, t0, ex_finish 
    csrrd    t0, csr_crmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    li       t1, 0x0 
    bne      t1, t0, ex_finish
    csrrd    t0, csr_prmd 
    li       t1, 0x7 
    and      t0, t0, t1 
    bne      t0, t5, ex_finish 
    lu12i.w  s2, 0x60 
    b        ex_finish  
    
ex_finish:
    csrrd    t1, csr_era 
    addi.w   t1, t1, 0x4 
    csrwr    t1, csr_era 
    bne      s2, zero, ex_ret
    lu12i.w  s2, 0xffff 
ex_ret:
    ertn

locate:

    LI (a0, LED_RG1_ADDR)
    LI (a1, LED_RG0_ADDR)
    LI (a2, LED_ADDR)
    LI (s1, NUM_ADDR)

    LI (t1, 0x0002)
    LI (t2, 0x0001)
    LI (t3, 0x0000ffff)
    lu12i.w   s3, 0
    NOP4

    st.w      t1, a0, 0
    st.w      t2, a1, 0
    st.w      t3, a2, 0
    st.w      s3, s1, 0
    lu12i.w   s0, 0
    NOP4
inst_test:
############################
###lab3 test
#if lab3
    bl n1_lu12i_w_test    #lu12i.w
    bl idle_1s
    
    bl n2_add_w_test   #add.w
    bl idle_1s
    
    bl n3_addi_w_test  #add.w
    bl idle_1s
    
    bl n4_sub_w_test   #sub.w
    bl idle_1s
    
    bl n5_slt_test    #slt
    bl idle_1s
    
    bl n6_sltu_test   #sltu
    bl idle_1s
    
    bl n7_and_test    #and
    bl idle_1s
    
    bl n8_or_test     #or
    bl idle_1s
    
    bl n9_xor_test    #xor
    bl idle_1s
    
    bl n10_nor_test   #nor
    bl idle_1s
    
    bl n11_slli_w_test   #slli.w
    bl idle_1s
    
    bl n12_srli_w_test   #srli.w
    bl idle_1s
    
    bl n13_srai_w_test   #srai.w
    bl idle_1s
    
    bl n14_ld_w_test    #ld.w
    bl idle_1s
    
    bl n15_st_w_test    #st.w
    bl idle_1s
    
    bl n16_beq_test   #beq
    bl idle_1s
    
    bl n17_bne_test   #bne
    bl idle_1s
    
    bl n18_bl_test   #bl
    bl idle_1s
    
    bl n19_jirl_test    #jirl
    bl idle_1s
    
    bl n20_b_test    #b
    bl idle_1s
    
#endif
############################
############################
###lab6 test
#if lab6
    bl n21_pcaddu12i_test   #pcaddu12i
    bl idle_1s
    
    bl n22_slti_test   #slti
    bl idle_1s
    
    bl n23_sltui_test  #sltui
    bl idle_1s
    
    bl n24_andi_test   #andi
    bl idle_1s
    
    bl n25_ori_test    #ori
    bl idle_1s
    
    bl n26_xori_test   #xori
    bl idle_1s
    
    bl n27_sll_w_test   #sll.w
    bl idle_1s
    
    bl n28_sra_w_test   #sra.w
    bl idle_1s
    
    bl n29_srl_w_test   #srl.w
    bl idle_1s
    
    bl n30_div_w_test    #div.w
    bl idle_1s
    
    bl n31_div_wu_test   #div.wu
    bl idle_1s
    
    bl n32_mul_w_test   #mul.w
    bl idle_1s
    
    bl n33_mulh_w_test  #mulh.w
    bl idle_1s
    
    bl n34_mulh_wu_test   #mulh.wu
    bl idle_1s
    
    bl n35_mod_w_test   #mod.w
    bl idle_1s
    
    bl n36_mod_wu_test   #mod.wu
    bl idle_1s
    
#endif
############################
############################
###lab7 test
#if lab7
    bl n37_blt_test          #blt
    bl idle_1s
    
    bl n38_bge_test       #bge
    bl idle_1s
    
    bl n39_bltu_test       #bltu
    bl idle_1s
    
    bl n40_bgeu_test       #bgeu
    bl idle_1s
    
    bl n41_ld_b_test       #ld.b
    bl idle_1s
    
    bl n42_ld_h_test     #ld.h
    bl idle_1s
    
    bl n43_ld_bu_test     #ld.bu
    bl idle_1s
    
    bl n44_ld_hu_test       #ld.hu
    bl idle_1s
    
    bl n45_st_b_test       #st.b
    bl idle_1s
    
    bl n46_st_h_test    #st.h
    bl idle_1s
    
#endif
############################
############################
###lab8 test
#if lab8 
lab8_csr_init:
    csrwr     zero, csr_prmd 
    csrwr     zero, csr_era 
    csrwr     zero, csr_eentry 

    li t0, 0x1c008000 
    csrwr t0, csr_eentry 

    bl n47_syscall_ex_test       #syscall
    bl idle_1s
#endif 
############################
############################
###lab9 test 
#if lab9 
lab9_csr_init:
    csrwr     zero, csr_prmd 
    csrwr     zero, csr_era 
    csrwr     zero, csr_eentry 
    csrwr     zero, csr_badv 
    csrwr     zero, csr_save0 
    csrwr     zero, csr_save1
    csrwr     zero, csr_save2 
    csrwr     zero, csr_save3 
    csrwr     zero, csr_tcfg

    li t0, 0x1c008000 
    csrwr t0, csr_eentry 

    bl n48_brk_ex_test         #brk ex 
    bl idle_1s 

    bl n49_ti_ex_test          #timer int ex 
    bl idle_1s 

#ifndef ENABLE_TRACE
    bl n50_ine_ex_test         #ine ex 
    bl idle_1s  
#endif

#ifndef ENABLE_TRACE
    bl n51_soft_int_ex_test    #soft int ex 
    bl idle_1s 
#endif

    bl n52_adef_ex_test         #adef ex 
    bl idle_1s  

    bl n53_ale_ld_w_ex_test     #ld.w ale ex 
    bl idle_1s 

    bl n54_ale_ld_h_ex_test     #ld.h ale ex 
    bl idle_1s 

    bl n55_ale_ld_hu_ex_test    #ld.hu ale ex 
    bl idle_1s 
    
    bl n56_ale_st_h_ex_test      #st.h ale ex 
    bl idle_1s 

    bl n57_ale_st_w_ex_test      #st.w ale ex 
    bl idle_1s 

    bl n58_ti_ex_idle_test      #timer int ex with idle 
    bl idle_1s  

#ifndef ENABLE_TRACE
    bl n59_rdcnt_test          #rdcntvl.w and rdcntvh.w test 
    bl idle_1s 
#endif

#ifndef ENABLE_TRACE
    bl n60_atomic_ins_test      #ll.w and sc.w test 
    bl idle_1s 
#endif
#endif

test_end:
    LI  (s0, TEST_NUM)
    NOP4
    beq s0, s3, 1f
    nop

    LI (a0, LED_ADDR)
	  LI (a1, LED_RG1_ADDR)
    LI (a2, LED_RG0_ADDR)
	
    LI (t1, 0x0002)
    NOP4
    
	  st.w    zero, a0, 0
    st.w    t1, a1, 0
    st.w    t1, a2, 0
    b  2f
    nop
1:
    LI (t1, 0x0001)
    LI (a0, LED_RG1_ADDR)
	  LI (a1, LED_RG0_ADDR)
    NOP4
    st.w    t1, a0, 0
    st.w    t1, a1, 0

2:
	//LI (t1, 0xff)
	//LI (t0, UART_ADDR)
	//sw t1, 0(t0)

	bl test_finish

idle_1s:
    LI (t0,SW_INTER_ADDR)
    LI (t1, 0xaaaa)

    #initial t3
    ld.w    t2, t0, 0   #switch_interleave: {switch[7],1'b0, switch[6],1'b0...switch[0],1'b0}
    NOP4
    xor     t2, t2, t1
    NOP4
    slli.w  t3, t2, 9     #t3 = switch interleave << 9
    NOP4
    addi.w  t3, t3, 1
    NOP4

sub1:  
    addi.w  t3, t3, -1

    #select min{t3, switch_interleave}
    ld.w    t2, t0, 0   #switch_interleave: {switch[7],1'b0, switch[6],1'b0...switch[0],1'b0}
    NOP4
    xor     t2, t2, t1
    NOP4
    slli.w  t2, t2, 9     #switch interleave << 9
    NOP4
    sltu    t4, t3, t2
    NOP4
    bne     t4, zero, 1f 
    addi.w  t3, t2, 0
    NOP4
1:
    bne     t3, zero, sub1
    jirl    zero, ra, 0
